home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / demostu2 / tunnel2.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-12-15  |  5.0 KB  |  277 lines

  1. PROGRAM Tunnel2;
  2. {
  3.   Tunnel2
  4.   - by Bjarke Viksφe
  5.   aug 1994
  6.  
  7.   A better version.
  8.   Skipped the screen mode $13. Screen mode is instead 320x200x16.
  9.   Plots are made to a buffer. It is made 256 bytes wide, so we can
  10.   address (x,y) fast.
  11.   When dots are drawn, buffer is dumped to display screen. Still use
  12.   triple buffering though.
  13. }
  14.  
  15. {$A+,B-,G+,E+,I+,N-,X+}
  16.  
  17.  
  18. USES
  19.     DEMOINIT;
  20.  
  21. {$DEFINE DEBUG}
  22.  
  23. CONST
  24.     NUMBER_CIRCLES = 64;
  25.     NUMBER_DOTS = 64;
  26.     NUMBER_ANIMS = 8;
  27.  
  28. TYPE
  29.     pCoordBuffer = ^CoordBuffer;
  30.     CoordBuffer = array[0..(NUMBER_CIRCLES*NUMBER_DOTS*2)-1] of integer;
  31.  
  32. VAR
  33.     sinustabel : array[0..639] of integer;
  34.     v1 : word;
  35.     cos1,sin1 : integer;
  36.  
  37.     pos : word;
  38.     xpos, ypos : word;
  39.  
  40.     coords : array[0..NUMBER_ANIMS-1] of pCoordBuffer;
  41.     buffer : pScreen;
  42.  
  43.  
  44. CONST
  45.     display1 : word = $0000;
  46.     display2 : word = $4000;
  47.     display3 : word = $8000;
  48.  
  49.  
  50. (*------------------------------------------------*)
  51.  
  52. procedure SetupSinus;
  53. var
  54.     i : integer;
  55.     v, vadd : real;
  56. begin
  57.     v:=0.0;
  58.     vadd:=(2.0*pi/512.0);
  59.     for i:=0 to 639 do begin
  60.         sinustabel[i]:=round(sin(v)*32767);
  61.         v:=v+vadd;
  62.     end;
  63. end;
  64.  
  65. procedure SetupCoords;
  66. {Precalc circle coords.
  67.  For each anim the start-rotation angle is changed a bit, so it looks
  68.  like the whole lot turns around}
  69. var
  70.     h,i,j,k : integer;
  71.     v1 : word;
  72.     cos1,sin1 : integer;
  73.     x : integer;
  74.     x1,y1 : longint;
  75. begin
  76.     for i:=0 to NUMBER_ANIMS-1 do New(coords[i]);
  77.  
  78.     for h:=0 to NUMBER_ANIMS-1 do begin
  79.         k:=0;
  80.         x:=80;
  81.         for i:=1 to NUMBER_CIRCLES do begin
  82.             {set start angle}
  83.             v1:=h;
  84.             for j:=1 to NUMBER_DOTS do begin
  85.                 sin1:=sinustabel[v1 AND 511];
  86.                 cos1:=sinustabel[(v1 AND 511)+128];
  87.                 {calc dot coordinate}
  88.                 x1:=LongMul(x,sin1) DIV 32768;
  89.                 y1:=LongMul(x,cos1) DIV 32768;
  90.                 {perspective calc... x1 is lower because of screen aspect}
  91.                 x1:=LongDiv(x1 SHL 8,700);
  92.                 y1:=LongDiv(y1 SHL 8,800);
  93.                 coords[h]^[k]:=y1;
  94.                 coords[h]^[k+1]:=x1;
  95.                 inc(k,2);
  96.                 inc(v1,512 DIV NUMBER_DOTS);
  97.             end;
  98.             inc(x,8);
  99.         end;
  100.     end;
  101. end;
  102.  
  103.  
  104. (*------------------------------------------------*)
  105.  
  106. procedure InitDemo;
  107. var
  108.     p : pointer;
  109.     i : integer;
  110. begin
  111.     ClearWholeScreen;
  112.     SetupSinus;
  113.     SetupCoords;
  114.  
  115.     {allocate memory for buffer. Offset MUST be $0000 though!!!}
  116.     New(buffer);
  117.     while Ofs(buffer^)<>0 do begin
  118.         Dispose(buffer);
  119.         GetMem(p,1); {does this really work? Think not!}
  120.         New(buffer);
  121.     end;
  122.     FillChar(buffer^,SizeOf(ScreenType),#0);
  123.  
  124.     pos:=0;
  125.     xpos:=0; ypos:=0;
  126. end;
  127.  
  128. procedure UninitDemo;
  129. var
  130.     i : integer;
  131. begin
  132.     Dispose(buffer);
  133.     for i:=0 to NUMBER_ANIMS-1 do Dispose(coords[i]);
  134. end;
  135.  
  136.  
  137. (*------------------------------------------------*)
  138.  
  139. procedure SwapDisplay;
  140. var
  141.     temp : word;
  142. begin
  143.     temp:=display3;
  144.     display3:=display2;
  145.     display2:=display1;
  146.     display1:=temp;
  147.     SetAddress(Ptr(SEGA000,display2));
  148. end;
  149.  
  150. procedure MoveBuffer; assembler;
  151. {Move buffer to display memory}
  152. asm
  153.     push    ds
  154.  
  155.     mov    es,SEGA000
  156.     mov    di,display1
  157.     lds    si,buffer
  158.     DB LONG; xor ax,ax
  159.     mov    bx,-4
  160.     mov    dx,199            {ysize}
  161.     cld
  162. @yloop:
  163.     mov    cl,40/4
  164. @xloop:
  165.     movsw                        {move buffer word to video memory}
  166.     movsw
  167.     DB LONG; mov [si+bx],ax        {clear the buffer again}
  168.     dec    cl
  169.     jnz    @xloop
  170.  
  171.     add    si,256-40
  172.     dec    dx
  173.     jnz    @yloop
  174.  
  175.     pop    ds
  176. end;
  177.  
  178.  
  179. (*------------------------------------------------*)
  180.  
  181. procedure DrawRingWithCut(x,y : integer; coords : pointer); assembler;
  182. asm
  183.     push    ds
  184.     push    bp
  185.  
  186.     les    ax,buffer
  187.     lds    si,coords
  188.     mov    dx,y
  189.     mov    bp,x
  190.     mov    bl,NUMBER_DOTS
  191.     mov    bh,$80
  192.     cld
  193. @loop:
  194.     lodsw                    {get y}
  195.     add    ax,dx
  196.     mov    cx,ax
  197.     lodsw                    {get x}
  198.     add    ax,bp
  199.     cmp    ax,320        {dots outside xpos [0..319] are not drawn}
  200.     jae    @none
  201.     cmp    cx,200        {dots outside ypos [0..199] are not drawn}
  202.     jae    @none
  203.     mov    ch,al            {calc offset address}
  204.     shr    ax,3
  205.     mov    ah,cl
  206.     mov    di,ax
  207.     mov    al,bh            {calc bit pos}
  208.     mov    cl,ch
  209.     ror    al,cl
  210.     or        [es:di],al
  211. @none:
  212.     dec    bl
  213.     jnz    @loop
  214.  
  215.     pop    bp
  216.     pop    ds
  217. end;
  218.  
  219.  
  220. (*------------------------------------------------*)
  221.  
  222. procedure RunOnce;
  223. var
  224.     x,y,z : integer;
  225.     i,j : integer;
  226.     tempx, tempy    : word;
  227. begin
  228.     SwapDisplay;
  229. {$IFNDEF DEBUG}
  230.     while retraces=0 do ;
  231.     retraces:=0;
  232. {$ELSE}
  233.     i:=total_retraces;
  234.     while i=total_retraces do ;
  235.     SetRGB(0,20,0,0);
  236. {$ENDIF}
  237.  
  238.     tempx:=xpos; tempy:=ypos;
  239.     z:=400;
  240.  
  241.     j:=0;
  242.     for i:=1 to NUMBER_CIRCLES do begin
  243.         {find circles' position}
  244.         x := 160+LongDiv(sinustabel[tempx AND 511],z);
  245.         y := 100+LongDiv(sinustabel[tempy AND 511],z);
  246.         DrawRingWithCut(x,y,@coords[pos]^[j]);
  247.         {move next circle in sinus-pos}
  248.         inc(tempx,6); inc(tempy,5);
  249.         {next circle is a bit longer back}
  250.         inc(z,25);
  251.         inc(j,NUMBER_DOTS*2);
  252.     end;
  253.     MoveBuffer;
  254.  
  255.     dec(xpos,2);
  256.     inc(ypos,1);
  257.     pos:=(pos+1) MOD NUMBER_ANIMS;
  258.  
  259. {$IFDEF DEBUG}
  260.     SetRGB(0,0,0,0);
  261.     while KeyHit[26] do ; {Hit 'P' to pause in debug mode}
  262. {$ENDIF}
  263. end;
  264.  
  265.  
  266. begin
  267.     SetScreenMode(MODE320x200x16);
  268.     Screen_Off;
  269.     InitDemo;
  270.     Screen_On;
  271.     SetAllInterrupts;
  272.     repeat RunOnce until Key='e'; {press ESCape key to exit}
  273.     RestoreAllInterrupts;
  274.     UninitDemo;
  275.     SetScreenMode(TEXTMODE);
  276. end.
  277.